// -*-mode:c++; coding:utf-8-*-

#if 0

#ifndef _BITS_HPP_KEBING_
#define _BITS_HPP_KEBING_ "hepengfei"

//
// about endianness, see
// http://www.cs.umass.edu/~verts/cs32/endian.html
// 

#include <endian.h>
#include <stdint.h>

namespace bits
{

	//
	// swap_byte_order - swap byte order from one to another
	//
	// only keep unsigned versions
	// 

	inline
	uint8_t swap_byte_order (uint8_t n) {
		return n;
	}
	// inline
	// int8_t swap_byte_order (int8_t n) {
	// 	return n;
	// }

	inline
	uint16_t swap_byte_order (uint16_t n) {
		return (((n & 0x00FF) << 8 ) |
			((n & 0xFF00) >> 8 ));
	}
	// inline
	// int16_t swap_byte_order (int16_t n) {
	// 	return (((n & 0x00FF) << 8 ) |
	// 		((n & 0xFF00) >> 8 ));
	// }

	inline
	uint32_t swap_byte_order (uint32_t n) {
		return (((n & 0x000000FF) << 24) |
			((n & 0x0000FF00) << 8 ) |
			((n & 0x00FF0000) >> 8 ) |
			((n & 0xFF000000) >> 24));
	}
	// inline
	// int32_t swap_byte_order (int32_t n) {
	// 	return (((n & 0x000000FF) << 24) |
	// 		((n & 0x0000FF00) << 8 ) |
	// 		((n & 0x00FF0000) >> 8 ) |
	// 		((n & 0xFF000000) >> 24));
	// }

	inline
	uint64_t swap_byte_order (uint64_t n) {
		return (((n & 0x00000000000000FFULL) << 56) |
			((n & 0x000000000000FF00ULL) << 40) |
			((n & 0x0000000000FF0000ULL) << 24) |
			((n & 0x00000000FF000000ULL) << 8 ) |
			((n & 0x000000FF00000000ULL) >> 8 ) |
			((n & 0x0000FF0000000000ULL) >> 24) |
			((n & 0x00FF000000000000ULL) >> 40) |
			((n & 0xFF00000000000000ULL) >> 56));
	}
	// inline
	// int64_t swap_byte_order (int64_t n) {
	// 	return (((n & 0x00000000000000FFULL) << 56) |
	// 		((n & 0x000000000000FF00ULL) << 40) |
	// 		((n & 0x0000000000FF0000ULL) << 24) |
	// 		((n & 0x00000000FF000000ULL) << 8 ) |
	// 		((n & 0x000000FF00000000ULL) >> 8 ) |
	// 		((n & 0x0000FF0000000000ULL) >> 24) |
	// 		((n & 0x00FF000000000000ULL) >> 40) |
	// 		((n & 0xFF00000000000000ULL) >> 56));
	// }

	//
	// type_selector - get the unsigned type name with the same byte length
	// 

	template<unsigned int bytes>
	struct byte_type;

	template<>
	struct byte_type<1> { typedef uint8_t type; };

	template<>
	struct byte_type<2> { typedef uint16_t type; };

	template<>
	struct byte_type<4> { typedef uint32_t type; };

	template<>
	struct byte_type<8> { typedef uint64_t type; };
	
	template<typename T>
	struct type_selector { typedef typename byte_type<sizeof(T)>::type type; };

	//
	// byte_order types
	//

	struct little_endian {};
	struct big_endian {};
	
	typedef big_endian net_byte_order;
#if __BYTE_ORDER == __LITTLE_ENDIAN
	typedef little_endian host_byte_order;
#else
	typedef big_endian host_byte_order;
#endif

	//
	// is_little_endian -
	//

	template<typename byte_order>
	struct is_little_endian { enum { value = 0 }; };
	template<>
	struct is_little_endian<little_endian> { enum { value = 1 }; };

	//
	// reversed_byte_order - return the reversed byte order
	//
	
	template<typename byte_order>
	struct reversed_byte_order;

	template<>
	struct reversed_byte_order<little_endian> {
		typedef big_endian value; // type
	};

	template<>
	struct reversed_byte_order<big_endian> {
		typedef little_endian value; // type
	};

	//
	// is_same_byte_order
	// 

	template<typename byte_order1,
		 typename byte_order2>
	struct is_same_byte_order;

	template<typename byte_order>
	struct is_same_byte_order<byte_order, byte_order> { enum {value = 1}; };

	template<typename byte_order>
	struct is_same_byte_order<byte_order, typename reversed_byte_order<byte_order>::value> { enum {value = 0}; };

	//
	// integer_cast - safely cast char array to an integer
	//
	// do NOT use reinterpret_cast to do this like follows:
	// integer = *reinterpret_cast<Integer*>(buffer);
	// because of byte alignment, you may got ZERO from that.
	//

	// byte_index - 按照字节序，获取该整数第byte_n个字节的下标，byte_n从0开始
	template<typename Integer, typename byteorder, size_t byte_n>
	struct byte_index;
	
	template<typename Integer, size_t byte_n>
	struct byte_index<Integer, little_endian, byte_n> {
		// static_assert<byte_n < sizeof(Integer)>
		enum { value = byte_n };
	};

	template<typename Integer, size_t byte_n>
	struct byte_index<Integer, big_endian, byte_n> {
		// static_assert<byte_n < sizeof(Integer)>
		enum { value = sizeof(Integer) - 1 - byte_n };
	};
	
	template<typename Integer, typename byteorder, size_t byte_n>
	struct integer_buffer_helper {
		static inline
		Integer get(const char *buffer) {
			return (static_cast<Integer>(buffer[byte_index<Integer, byteorder, byte_n>::value]) << (byte_n * 8))
				| integer_buffer_helper<Integer, byteorder, byte_n - 1>::get(buffer);
		}
		
		//template<typename Integer, typename byteorder>
		static inline
		void put(char *buffer, Integer n) {
			buffer[byte_n] = reinterpret_cast<char*>(&n)[byte_index<Integer, byteorder, byte_n>::value];
			integer_buffer_helper<Integer, byteorder, byte_n - 1>::put(buffer, n); // recurisive
		}
	};

	template<typename Integer, typename byteorder>
	struct integer_buffer_helper<Integer, byteorder, 0> {
		static inline
		Integer get(const char *buffer) {
			return (static_cast<Integer>(buffer[byte_index<Integer, byteorder, 0>::value]) << (0 * 8));
		}
		
		//template<typename Integer, typename byteorder>
		static inline
		void put(char *buffer, Integer n) {
			buffer[0] = reinterpret_cast<char*>(&n)[byte_index<Integer, byteorder, 0>::value];
		}
	};
	
	// get_integer or integer_cast
	template<typename byteorder, typename Integer>
	Integer get_integer(const char *buffer) {
		return integer_buffer_helper<Integer, byteorder, sizeof(Integer) - 1>::get(buffer);
	}

	template<typename byteorder, typename Integer>
	Integer put_integer(char *buffer, Integer n) {
		integer_buffer_helper<Integer, byteorder, sizeof(Integer) - 1>::put(buffer, n);
	}
	
	// template<typename byteorder, typename Integer>
	// Integer integer_cast(const char (&buffer)[sizeof(Integer)]) {
	// 	return integer_cast<byteorder, Integer>(buffer);
	// }
	// template<typename byteorder, typename Integer>
	// Integer integer_cast(const boost::array<sizeof(Integer)> &buffer) {
	// 	return integer_cast<byteorder, Integer>(&buffer[0]);
	// }

	//
	// byte_order_cast_helper - the helper class for byte_order_cast
	// 

	template<typename from, typename to>
	struct byte_order_cast_helper {};

	template<typename order> // the same order version
	struct byte_order_cast_helper<order, order> {
		template<typename Integer>
		static inline
		Integer cast(Integer n) {
			return n;
		}
	};

	template<typename order> // the different order version
	struct byte_order_cast_helper<order,
				 typename reversed_byte_order<order>::value> {
		template<typename Integer>
		static inline
		Integer cast(Integer n) {
			return static_cast<Integer>(swap_byte_order(static_cast<typename type_selector<Integer>::type>(n)));
		}
	};

	//
	// byte_order_cast - provide a cast type operator
	//
	// int n; 
	// byte_order_cast<host_byte_order, net_byte_order>(n);
	// 

	template<typename from,
		 typename to,
		 typename Integer>
	inline
	Integer byte_order_cast(Integer n) {
		return byte_order_cast_helper<from, to>::cast(n);
	}
	
	// 函数模板部分特例化是不允许的
	// template<typename order,
	// 	 typename Integer>
	// Integer byte_order_cast<order, order, Integer>(Integer n) {
	// 	return n;
	// }
	// template<typename order,
	// 	 typename Integer>
	// Integer byte_order_cast<order, typename reversed_byte_order<order>::value, Integer>(Integer n) {
	// 	return swap_byte_order(n);
	// }
	
	
	//
	// from_order, to_order - swap between order with host_order
	//

	template<typename order,
		 typename Integer>
	inline
	Integer from_byte_order_cast(Integer n) {
		return byte_order_cast<order, host_byte_order, Integer>(n);
	}

	template<typename order,
		 typename Integer>
	inline
	Integer to_byte_order_cast(Integer n) {
		return byte_order_cast<host_byte_order, order, Integer>(n);
	}

	//
	// ntoh, hton - the famous system function
	// 

	template<typename Integer>
	inline
	Integer ntoh(Integer n) {
		return byte_order_cast<net_byte_order, host_byte_order>(n);
	}
	template<typename Integer>
	inline
	Integer hton(Integer n) {
		return byte_order_cast<host_byte_order, net_byte_order>(n);
	}


	//
	// 以下的枚举方式被抛弃，改为使用上面的类型方式的实现
	// 

#if false

	enum byte_order
	{
		BO_LITTLE_ENDIAN,
		BO_BIG_ENDIAN,

#if __BYTE_ORDER == __LITTLE_ENDIAN
		BO_HOST = BO_LITTLE_ENDIAN,
#else
		BO_HOST = BO_BIG_ENDIAN,
#endif

		BO_NET = BO_BIG_ENDIAN
	};

	//
	// which_byte_order - return the order name
	//
	
	template<int order>
	struct which_byte_order {};
	template<>
	struct which_byte_order<BO_LITTLE_ENDIAN>
	{
		static const byte_order value = BO_LITTLE_ENDIAN;
	};
	template<>
	struct which_byte_order<BO_BIG_ENDIAN>
	{
		static const byte_order value = BO_BIG_ENDIAN;
	};

	//
	// reverse_byte_order - return the reverse byte order
	//
	
	template<int order>
	struct reverse_byte_order {};
	template<>
	struct reverse_byte_order<BO_LITTLE_ENDIAN>
	{
		static const byte_order value = BO_BIG_ENDIAN;
	};
	template<>
	struct reverse_byte_order<BO_BIG_ENDIAN>
	{
		static const byte_order value = BO_LITTLE_ENDIAN;
	};

	//
	// byte_order_swapper - call the swap function ONLY as necessary
	// 

	template<byte_order from, byte_order to>
	struct byte_order_swapper // default is different byte order
	{
		template<typename Integer>
		static inline
		Integer swap(Integer n) {
			return swap_byte_order(n);
		}
	};
	template<byte_order order>	// specialize the same byte order version
	struct byte_order_swapper<order, order>
	{
		template<typename Integer>
		static inline
		Integer swap(Integer n) {
			return n;
		}
	};

	#endif	// false

} // namespace bits

#endif	// _BITS_HPP_KEBING_

#endif	// 0
